﻿using EntityFrameworkETL.Interceptors;
using EntityFrameworkETL.Interfaces;
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Data.Entity;
using System.Data.Entity.Infrastructure.Interception;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace EntityFrameworkETL
{
    public class ETL
    {
        public ETL(Func<string, DbContext> constructor, string sourceConnection, string destinationConnection)
        {
            Repository = new Repository(() => constructor(sourceConnection), () => constructor(destinationConnection));
            ExecuteBatchCommands = new BatchAndExecuteCommands(Repository.DestinationConnectionString(), new ExecuteNonQuery());
        }

        public ETL(Func<DbContext> sourceContextFunction, Func<DbContext> destinationContextFunction)
        {
            Repository = new Repository(sourceContextFunction, destinationContextFunction);
            ExecuteBatchCommands = new BatchAndExecuteCommands(Repository.DestinationConnectionString(), new ExecuteNonQuery());
        }

        public ETL(IRepository repository, IExecuteBatchCommands executeBatchCommands)
        {
            Repository = repository;
            ExecuteBatchCommands = executeBatchCommands;
        }

        public IRepository Repository { get; set; }
        public IExecuteBatchCommands ExecuteBatchCommands { get; set; }

        public void BatchInserts<T>(int batchSize, bool identityInsert, Func<IQueryable<T>, IQueryable<T>> query=null) where T : class
        {
            List<T> source = Repository.SelectSource<T>(query).ToList();
            while (source.Count > 0)
            {
                if (source.Count < batchSize)
                    batchSize = source.Count;
                List<T> batch = source.Take(batchSize).ToList();
                source.RemoveRange(0, batchSize);
                var commands = Repository.GetInsertCommands<T>(batch, identityInsert);
                ExecuteBatchCommands.Execute(commands);
            }
        }

        public void DeleteAll<T>() where T : class
        {
            Repository.DeleteAll<T>();
        }
    }
}
